package com.tegistuff.webos.run.debugger.infrastructure;

import com.palm.webos.tools.internal.debugger.AppDebugSession;
import com.tegistuff.webos.run.debugger.WebOSDebugProcess;
import com.tegistuff.webos.run.debugger.WebOSDebuggerProxy;
import com.tegistuff.webos.run.debugger.commands.BaseWebOSCommand;

import java.util.LinkedList;
import java.util.List;

/**
 * WebOSCommandSpooler.java
 *
 * Stores and sequentializes commands that operate on the V8 debugger.
 *
 * Copyright (C) 2011-2012 Timo Tegtmeier.
 * All rights reserved.
 */
public class WebOSCommandSpooler {

    private WebOSDebugProcess myDebugProcess;
    private List<BaseWebOSCommand> myCommands;
    private BaseWebOSCommand myCurrentCommand;

    public WebOSCommandSpooler(WebOSDebugProcess debugProcess) {
        myDebugProcess = debugProcess;
        myCommands = new LinkedList<BaseWebOSCommand>();
    }

    public void onDebuggerConnected() {
        processCommand();
    }

    public BaseWebOSCommand runCommand(BaseWebOSCommand command) {
        return runCommand(command, null);
    }

    public BaseWebOSCommand runCommand(BaseWebOSCommand command, BaseWebOSCommand listener) {
        command.setListener(listener);
        myCommands.add(command);
        if(getDebuggerProxy().isReady())
            processCommand();
        return command;
    }

    public WebOSDebugProcess getDebugProcess() {
        return myDebugProcess;
    }

    public WebOSDebuggerProxy getDebuggerProxy() {
        return myDebugProcess.getDebuggerProxy();
    }

    public AppDebugSession getAppDebugSession() {
        return myDebugProcess.getDebuggerProxy().getAppDebugSession();
    }

    private void processCommand() {
        if(myCurrentCommand != null)
            return;
        if(myCommands.isEmpty())
            return;
        myCurrentCommand = myCommands.get(0);
        try {
            myCurrentCommand.setSpooler(this);
            myCurrentCommand.execute();
        } catch(Exception e) {
            myDebugProcess.reportInternalError(e);
        }
    }

    public void done(BaseWebOSCommand command) {
        assert command == myCurrentCommand;
        myCommands.remove(command);
        myCurrentCommand = null;
        command.notifyAll();
        processCommand();
    }

    public void clear() {
        myCommands.clear();
        if(myCurrentCommand != null)
            myCommands.add(myCurrentCommand);
    }
}
